/*
 * Fixed SAI APIs which are not based on P4 pipeline code.
 * Just sufficient to support testing & integrating bmv2's libsai.
 */
#include "utils.h"
#include "saiimpl.h"
#include "config.h"

#include <vector>

std::shared_ptr<dash::DashSai> dashSai = std::make_shared<dash::DashSai>();

#define API(A,api) case SAI_API_ ## A: *api_method_table = (void*)&dash_sai_ ## api ## _api_impl; break;

sai_status_t sai_api_query(
        _In_ sai_api_t api,
        _Out_ void **api_method_table)
{
    DASH_LOG_ENTER();

    switch((int)api)
    {
        API(HOSTIF,hostif);
        API(NEIGHBOR,neighbor);
        API(NEXT_HOP,next_hop);
        API(POLICER,policer);
        API(PORT,port);
        API(ROUTER_INTERFACE,router_interface);
        API(SWITCH,switch);
        API(BUFFER,buffer);
        API(DTEL,dtel);
        API(ACL,acl);

{% for api in api_names %}
        case SAI_API_{{ api | upper }}:
            *api_method_table = (void *)&dash_sai_{{ api }}_api_impl;
            break;

{% endfor %}
        default:

            DASH_LOG_WARN("api %d not supported", api);

            return SAI_STATUS_NOT_SUPPORTED;
    }

    return SAI_STATUS_SUCCESS;
}

sai_status_t sai_object_type_get_availability(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_type_t object_type,
        _In_ uint32_t attr_count,
        _In_ const sai_attribute_t *attr_list,
        _Out_ uint64_t *count)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_object_type_t sai_object_type_query(
        _In_ sai_object_id_t object_id)
{
    DASH_LOG_ENTER();

    return dashSai->objectTypeQuery(object_id);
}

sai_object_id_t sai_switch_id_query(
        _In_ sai_object_id_t object_id)
{
    DASH_LOG_ENTER();

    return dashSai->switchIdQuery(object_id);
}

sai_status_t sai_query_attribute_enum_values_capability(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_type_t object_type,
        _In_ sai_attr_id_t attr_id,
        _Inout_ sai_s32_list_t *enum_values_capability)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t sai_api_initialize(
        _In_ uint64_t flags,
        _In_ const sai_service_method_table_t *services)
{
    DASH_LOG_ENTER();

    return dashSai->apiInitialize(flags, services);
}

sai_status_t sai_api_uninitialize(void)
{
    DASH_LOG_ENTER();

    return dashSai->apiUninitialize();
}

sai_status_t sai_log_set(
        _In_ sai_api_t api,
        _In_ sai_log_level_t log_level)
{
    DASH_LOG_ENTER();

    return SAI_STATUS_SUCCESS;
}

sai_status_t sai_query_api_version(
        _Out_ sai_api_version_t *version)
{
    DASH_LOG_ENTER();

    if (version)
    {
        *version = SAI_API_VERSION;

        DASH_LOG_NOTICE("SAI headers version: %d", SAI_API_VERSION);

        return SAI_STATUS_SUCCESS;
    }

    DASH_LOG_ERROR("version parameter is NULL");

    return SAI_STATUS_INVALID_PARAMETER;
}

sai_status_t sai_query_stats_capability(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_type_t object_type,
        _Inout_ sai_stat_capability_list_t *stats_capability)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t sai_query_attribute_capability(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_type_t object_type,
        _In_ sai_attr_id_t attr_id,
        _Out_ sai_attr_capability_t *attr_capability)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t sai_dbg_generate_dump(
        _In_ const char *dump_file_name)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t sai_query_stats_st_capability(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_type_t object_type,
        _Inout_ sai_stat_st_capability_list_t *stats_capability)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t sai_tam_telemetry_get_data(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_list_t obj_list,
        _In_ bool clear_on_read,
        _Inout_ sai_size_t *buffer_size,
        _Out_ void *buffer)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t sai_bulk_object_clear_stats(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_type_t object_type,
        _In_ uint32_t object_count,
        _In_ const sai_object_key_t *object_key,
        _In_ uint32_t number_of_counters,
        _In_ const sai_stat_id_t *counter_ids,
        _In_ sai_stats_mode_t mode,
        _Inout_ sai_status_t *object_statuses)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}

sai_status_t sai_bulk_object_get_stats(
        _In_ sai_object_id_t switch_id,
        _In_ sai_object_type_t object_type,
        _In_ uint32_t object_count,
        _In_ const sai_object_key_t *object_key,
        _In_ uint32_t number_of_counters,
        _In_ const sai_stat_id_t *counter_ids,
        _In_ sai_stats_mode_t mode,
        _Inout_ sai_status_t *object_statuses,
        _Out_ uint64_t *counters)
{
    DASH_LOG_ENTER();

    DASH_LOG_WARN("not implemented");

    return SAI_STATUS_NOT_IMPLEMENTED;
}
